package com.semlab.server.enrichment;

import java.util.List;

import org.neo4j.graphdb.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.facebook.api.EducationEntry;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.FacebookProfile;
import org.springframework.social.facebook.api.Page;
import org.springframework.social.facebook.api.Reference;
import org.springframework.social.facebook.api.WorkEntry;
import org.springframework.social.facebook.api.impl.FacebookTemplate;
import org.springframework.stereotype.Component;

import com.semlab.server.graph.ConceptRepository;
import com.semlab.server.graph.Neo4jTemplate;
import com.semlab.server.graph.ProfileRepository;
import com.semlab.server.resources.Concept;
import com.semlab.server.resources.FType;
import com.semlab.server.resources.Profile;
import com.semlab.server.resources.RelationshipTypes;
import com.semlab.server.resources.RootNode;
import com.semlab.server.resources.SLog;
import com.semlab.shared.NamespaceConstants;

@Component
public class InsertProfileService {

    Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    ProfileRepository profiles;

    @Autowired
    ConceptRepository concepts;

    @Autowired
    RootNode root;

    @Autowired
    Neo4jTemplate template;

    private int likesLimit = -1;
    private int numOfParsedLikes = 0;

    public void process(String token, int numOfFriends, int numOfLikes) {
        likesLimit = numOfLikes;
        numOfParsedLikes = 0;
        log.debug("inserting profile");
        template.beginTransaction();
        log.debug("contacting facebook");
        Facebook facebook = new FacebookTemplate(token);
        FacebookProfile profile = facebook.userOperations().getUserProfile();

        log.debug("parsing profile ");
        Profile me = profiles.parseFacebookProfile(profile);
        Node profileNode = profiles.persist(me);

//        no need to parse my own movies
//        log.debug( "parsing movies");
//        parseMovies(profileNode, facebook, profile.getId());

        // parse friends
        List<FacebookProfile> friends = facebook.friendOperations()
                .getFriendProfiles(0, numOfFriends);
//        int num = -1;
        for (FacebookProfile friend : friends) {
//            num++;
//            if (num == numOfFriends) {
//                break;
//            }
            Profile nfriend = profiles.parseFacebookProfile(friend);
            Node friendNode = profiles.persist(nfriend);
            parseMovies(friendNode, facebook, friend.getId());
            profiles.makeFriends(me, nfriend);
        }
        root.relate(template.getNode(me.getNodeId()));
        template.finishTransaction();
    }

    private void parseBooks(Node profileNode, Facebook facebook, String id) {
        createLikes(facebook.likeOperations().getBooks(id), profileNode);
    }

    private void parseMovies(Node profileNode, Facebook facebook, String id) {
        createLikes(facebook.likeOperations().getMovies(id), profileNode);
    }

    private void createLikes(List<Page> list, Node profile) {
        for (org.springframework.social.facebook.api.Page page : list) {
            if (numOfParsedLikes >= likesLimit) {
                break;
            }
            numOfParsedLikes++;
            if (FType.isSupportedType(page.getCategory())) {
                String name = page.getName();
                log.debug( "saving page {} {}", page.getId(), name);
                Node concept = getConcept(page.getId(), name,
                        page.getCategory());
                template.relate(profile, concept, RelationshipTypes.LIKES);
            }
        }
    }

    private Node getConcept(String id, String name, String type) {
        Node indexed = concepts.getDomainNode(id);
        Concept concept = null;
        if (indexed == null) {
            concept = new Concept(id, name, type);
            Node back = concepts.persist(concept);
            template.setNodeProperty(back, NamespaceConstants.FB_HITS, 1);
            concepts.assignConceptForUpdate(concept);
            return back;
        } else {
//			boolean result = indexed.hasProperty(NamespaceConstants.FB_HITS);
//			if (!result) {
//				log.debug( "setting fb hits for", name);
//			} else {
            template.setNodeProperty(
                    indexed,
                    NamespaceConstants.FB_HITS,
                    Integer.parseInt(indexed.getProperty(
                            NamespaceConstants.FB_HITS).toString()) + 1);
            return indexed;
        }
    }

}